﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using HmmmIDE;
using System.Reflection.Emit;
using System.Diagnostics;
using HmmmIDE.Syntax;

namespace HmmmIDE.Debug
{
    public class MethodManager
    {
        public delegate void OneRegister(Register rX);
        public delegate void TwoRegister(Register rX, Register rY);
        public delegate void ThreeRegister(Register rX, Register rY, Register rZ);
        public delegate void OneRgisterOneNumber(Register rX, short n);
        public delegate void NoRegister();
        public delegate void OneNumber(short n);

        public Dictionary<string, Delegate> MethodDelegaets { get; set; }

        #region Constructor
        public MethodManager()
        {
            var dic = SyntaxManager.CommandRegex;
            this.MethodDelegaets = new Dictionary<string, Delegate>();

            foreach(var kvp in dic)
            {
                string methodName = kvp.Key;
                var methodInfo = typeof(Methods).GetMethod(methodName);
                int argCount = methodInfo.GetParameters().Length;
                Delegate method = null;

                if(argCount == 3)
                {
                    
                    method = Delegate.CreateDelegate(typeof(ThreeRegister), methodInfo);
                }
                else if(argCount == 2)
                {
                    var test = methodInfo.GetParameters();
                    if(test.Any(element=> element.ParameterType == typeof(short)))  // one register one short
                    {
                        method = Delegate.CreateDelegate(typeof(OneRgisterOneNumber), methodInfo);
                    }
                    // tow registers
                    else
                    {
                        method = Delegate.CreateDelegate(typeof(TwoRegister), methodInfo);
                    }
                }
                else if(argCount == 1)
                {
                    if (methodInfo.GetParameters().Any(element => element.ParameterType == typeof(short)))  // one short
                    {
                        method = Delegate.CreateDelegate(typeof(OneNumber), methodInfo);
                    }
                    // one register
                    else
                    {
                        method = Delegate.CreateDelegate(typeof(OneRegister), methodInfo);
                    }
                }
                else
                {
                    method = Delegate.CreateDelegate(typeof(NoRegister), methodInfo);
                }

                this.MethodDelegaets.Add(kvp.Key, method);
            }

        }

        #endregion
        /// <summary>
        /// Returns method delegate correspond to the command line code
        /// </summary>
        /// <param name="commandCode">Command code</param>
        /// <returns>Method delegate</returns>
        public Delegate GetMethod(string commandCode)
        {
            return MethodDelegaets[commandCode];
        }
    }
}
